/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jj2000.stg.ui;

import colorspace.ColorSpace;
import colorspace.ColorSpaceException;
import icc.ICCProfileException;
import java.awt.BorderLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.UnsupportedLookAndFeelException;
import jj2000.disp.BlkImgDataSrcImageProducer;
import jj2000.disp.ImgKeyListener;
import jj2000.disp.ImgScrollPane;
import jj2000.j2k.codestream.HeaderInfo;
import jj2000.j2k.codestream.reader.BitstreamReaderAgent;
import jj2000.j2k.codestream.reader.HeaderDecoder;
import jj2000.j2k.codestream.writer.FileCodestreamWriter;
import jj2000.j2k.codestream.writer.HeaderEncoder;
import jj2000.j2k.decoder.Decoder;
import jj2000.j2k.decoder.DecoderSpecs;
import jj2000.j2k.encoder.Encoder;
import jj2000.j2k.encoder.EncoderSpecs;
import jj2000.j2k.entropy.decoder.EntropyDecoder;
import jj2000.j2k.entropy.encoder.EntropyCoder;
import jj2000.j2k.entropy.encoder.PostCompRateAllocator;
import jj2000.j2k.fileformat.reader.FileFormatReader;
import jj2000.j2k.image.BlkImgDataSrc;
import jj2000.j2k.image.ImgDataConverter;
import jj2000.j2k.image.Tiler;
import jj2000.j2k.image.forwcomptransf.ForwCompTransf;
import jj2000.j2k.image.input.ImgReader;
import jj2000.j2k.image.input.ImgReaderPPM;
import jj2000.j2k.image.invcomptransf.InvCompTransf;
import jj2000.j2k.io.BEBufferedRandomAccessFile;
import jj2000.j2k.quantization.dequantizer.Dequantizer;
import jj2000.j2k.quantization.quantizer.Quantizer;
import jj2000.j2k.roi.ROIDeScaler;
import jj2000.j2k.roi.encoder.ROIScaler;
import jj2000.j2k.util.ParameterList;
import jj2000.j2k.wavelet.analysis.ForwardWT;
import jj2000.j2k.wavelet.synthesis.InverseWT;

/**
 *
 * @author teq
 */
public class MainForm extends javax.swing.JFrame {

    /**
     * Creates new form MainForm
     */
    public MainForm(String hostImgPath, String hiddenImgPath) {
        this();
        
        try {
            hostImageRdr = new ImgReaderPPM(hostImgPath);
            jHostImagePathTextField.setText(hostImgPath);
            hiddenImageRdr = new ImgReaderPPM(hiddenImgPath);
            jHiddenImagePathTextField.setText(hiddenImgPath);
        } catch (Exception ex) {
            MsgBox(ex.getMessage());
        }
        
    }
    
    public MainForm() {
        
        initComponents();
        
        hostImageISP = new ImgScrollPane();
        jHostImageDistPanel.add(hostImageISP, BorderLayout.CENTER);
        hostImageISP.addKeyListener(new ImgKeyListener(hostImageISP));
        jHostImageDistPanel.validate();
        
        hiddenImageISP = new ImgScrollPane();
        jHiddenImageDistPanel.add(hiddenImageISP, BorderLayout.CENTER);
        hiddenImageISP.addKeyListener(new ImgKeyListener(hiddenImageISP));
        jHiddenImageDistPanel.validate();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(final String args[]) {
        /*
         * Set system default look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        
        try {
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                
                MainForm form;
                
                if (args.length == 2) {
                    form = new MainForm(args[0], args[1]);
                } else {
                    form = new MainForm();
                }

                form.setVisible(true);
            }
        });
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jHostImagePathTextField = new javax.swing.JTextField();
        jChooseHostImageButton = new javax.swing.JButton();
        jViewHostImageButton = new javax.swing.JButton();
        jHostImageLabel = new javax.swing.JLabel();
        jHiddenImagePathTextField = new javax.swing.JTextField();
        jHiddenImageLabel = new javax.swing.JLabel();
        jChooseHiddenImageButton = new javax.swing.JButton();
        jViewHiddenImageButton = new javax.swing.JButton();
        jHiddenImageDistPanel = new javax.swing.JPanel();
        jHostImageDistPanel = new javax.swing.JPanel();
        jSeparator1 = new javax.swing.JSeparator();
        jSeparator2 = new javax.swing.JSeparator();
        jStartButton = new javax.swing.JButton();
        jBppSpinner = new javax.swing.JSpinner();
        jEncodedFileLengthTextField = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(600, 400));

        jHostImagePathTextField.setEditable(false);
        jHostImagePathTextField.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jHostImagePathTextFieldMouseClicked(evt);
            }
        });

        jChooseHostImageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/folder.png"))); // NOI18N
        jChooseHostImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jChooseHostImageButtonActionPerformed(evt);
            }
        });

        jViewHostImageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/magnifier.png"))); // NOI18N
        jViewHostImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jViewHostImageButtonActionPerformed(evt);
            }
        });

        jHostImageLabel.setText("Host image");

        jHiddenImagePathTextField.setEditable(false);
        jHiddenImagePathTextField.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jHiddenImagePathTextFieldMouseClicked(evt);
            }
        });

        jHiddenImageLabel.setText("Hidden image");

        jChooseHiddenImageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/folder.png"))); // NOI18N
        jChooseHiddenImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jChooseHiddenImageButtonActionPerformed(evt);
            }
        });

        jViewHiddenImageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/magnifier.png"))); // NOI18N
        jViewHiddenImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jViewHiddenImageButtonActionPerformed(evt);
            }
        });

        jHiddenImageDistPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Hidden image distortion"));
        jHiddenImageDistPanel.setLayout(new java.awt.BorderLayout());

        jHostImageDistPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Host image distortion"));
        jHostImageDistPanel.setLayout(new java.awt.BorderLayout());

        jSeparator2.setOrientation(javax.swing.SwingConstants.VERTICAL);

        jStartButton.setText("Start");
        jStartButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jStartButtonActionPerformed(evt);
            }
        });

        jBppSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(8.0f), Float.valueOf(0.01f), Float.valueOf(24.0f), Float.valueOf(0.5f)));

        jEncodedFileLengthTextField.setEditable(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jHostImageDistPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jHiddenImageDistPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jBppSpinner, javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(37, 37, 37)
                                .addComponent(jStartButton))
                            .addComponent(jEncodedFileLengthTextField, javax.swing.GroupLayout.Alignment.TRAILING)))
                    .addComponent(jSeparator1)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jHiddenImageLabel, javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jHostImageLabel, javax.swing.GroupLayout.Alignment.TRAILING))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jHiddenImagePathTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 663, Short.MAX_VALUE)
                            .addComponent(jHostImagePathTextField))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(jChooseHostImageButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jViewHostImageButton))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(jChooseHiddenImageButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jViewHiddenImageButton)))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jHostImageLabel)
                        .addComponent(jHostImagePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jViewHostImageButton)
                    .addComponent(jChooseHostImageButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jHiddenImageLabel)
                        .addComponent(jHiddenImagePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jViewHiddenImageButton)
                    .addComponent(jChooseHiddenImageButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jBppSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jStartButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jEncodedFileLengthTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 458, Short.MAX_VALUE))
                    .addComponent(jHostImageDistPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jHiddenImageDistPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jSeparator2))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jChooseHostImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jChooseHostImageButtonActionPerformed

        String fname = PickAnImagePathDialog();
        
        if("".equals(fname))
        {
            return;
        }
        
        jHostImagePathTextField.setText(fname);
        
        try {
            hostImageRdr = new ImgReaderPPM(jHostImagePathTextField.getText());
        } catch (Exception ex) {
            hostImageRdr = null;
            jHostImagePathTextField.setText("");
            MsgBox(ex.getMessage());
        }

    }//GEN-LAST:event_jChooseHostImageButtonActionPerformed

    private void jHostImagePathTextFieldMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jHostImagePathTextFieldMouseClicked

        if (hostImageRdr == null) {
            jChooseHostImageButton.doClick();
        }
        
    }//GEN-LAST:event_jHostImagePathTextFieldMouseClicked

    private void jHiddenImagePathTextFieldMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jHiddenImagePathTextFieldMouseClicked

        if (hiddenImageRdr == null) {
            jChooseHiddenImageButton.doClick();
        }
        
    }//GEN-LAST:event_jHiddenImagePathTextFieldMouseClicked

    private void jChooseHiddenImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jChooseHiddenImageButtonActionPerformed

        String fname = PickAnImagePathDialog();
        
        if("".equals(fname))
        {
            return;
        }
        
        jHiddenImagePathTextField.setText(fname);
        
        try {
            hiddenImageRdr = new ImgReaderPPM(jHiddenImagePathTextField.getText());
        } catch (Exception ex) {
            hiddenImageRdr = null;
            jHiddenImagePathTextField.setText("");
            MsgBox(ex.getMessage());
        }
        
    }//GEN-LAST:event_jChooseHiddenImageButtonActionPerformed

    private void jViewHostImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jViewHostImageButtonActionPerformed

        if (hostImageRdr != null)
        {
            if (viewHostImageFrame != null)
            {
                viewHostImageFrame.dispose();
            }
            
            viewHostImageFrame = new JFrame("Host image");
            
            ShowImageInFrame(viewHostImageFrame, hostImageRdr);
        }
        
    }//GEN-LAST:event_jViewHostImageButtonActionPerformed

    private void jViewHiddenImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jViewHiddenImageButtonActionPerformed

        if (hiddenImageRdr != null)
        {
            if(viewHiddenImageFrame != null)
            {
                viewHiddenImageFrame.dispose();
            }

            viewHiddenImageFrame = new JFrame("Hidden image");
            
            ShowImageInFrame(viewHiddenImageFrame, hiddenImageRdr);
        }
        
    }//GEN-LAST:event_jViewHiddenImageButtonActionPerformed

    private void jStartButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jStartButtonActionPerformed
        PerformImageEmbedding((float)jBppSpinner.getValue());
    }//GEN-LAST:event_jStartButtonActionPerformed

    private String PickAnImagePathDialog() {

        JFileChooser fc = new JFileChooser();
        int retVal = fc.showOpenDialog(this);
        if (retVal == JFileChooser.APPROVE_OPTION)
        {
            return fc.getSelectedFile().getAbsolutePath();
        }
        else
        {
            return "";
        }
        
    }

    private void MsgBox(String msg) {

        JOptionPane.showMessageDialog(this, msg);
        
    }
    
    private void ShowImageInFrame(JFrame frame, BlkImgDataSrc imgSrc) {
        
        ImgScrollPane isp = new ImgScrollPane(ImgScrollPane.SCROLLBARS_AS_NEEDED);
        frame.add(isp, BorderLayout.CENTER);
        isp.addKeyListener(new ImgKeyListener(isp));
        Image img = BlkImgDataSrcImageProducer.createImage(imgSrc, isp);
        isp.setImage(img);
        frame.setSize(imgSrc.getImgWidth(), imgSrc.getImgHeight());
        frame.setVisible(true);
        
    }
    
    private void PerformImageEmbedding(float rate) {
        
        try {
            
            if(hostImageRdr == null || hiddenImageRdr == null)
            {
                return;
            }
            
            File encodedFile = File.createTempFile("jj2k-", "-encoded");
            encodedFile.deleteOnExit();
            
            int flength = EncodeToFile(encodedFile, hostImageRdr, rate);
            jEncodedFileLengthTextField.setText(String.valueOf(flength));

            BlkImgDataSrc decoded = DecodeFromFile(encodedFile);

            Image img1 = BlkImgDataSrcImageProducer.createImage(decoded, hostImageISP);
            hostImageISP.setImage(img1);

            Image img2 = BlkImgDataSrcImageProducer.createImage(hiddenImageRdr, hiddenImageISP);
            hiddenImageISP.setImage(img2);
            
        } catch (Exception ex) {
            Logger.getLogger(MainForm.class.getName())
                    .log(Level.SEVERE, null, ex);
        }
        
    }
    
    private int EncodeToFile(File dst, ImgReader src, float rate)
            throws IOException {

        ParameterList defpl, pl;
        //<editor-fold defaultstate="collapsed" desc=" Prepare parameters ">

        defpl = new ParameterList();

        String[][] param = Encoder.getAllParameters();

        for (int i = param.length - 1; i >= 0; i--) {
            if (param[i][3] != null){
                defpl.put(param[i][0], param[i][3]);
            }
        }

        pl = new ParameterList(defpl);

        pl.put("file_format", "on");

        //</editor-fold>

        Tiler imgtiler = new Tiler(src,
                                   /*refx=*/0, /*refy=*/0,
                                   /*trefx=*/0, /*trefy=*/0,
                                   /*tw=*/0, /*th=*/0);

        EncoderSpecs encSpec = new EncoderSpecs(src.getNumTiles(),
                                                N_COMP, src, pl);

        ForwCompTransf fctransf = new ForwCompTransf(imgtiler,encSpec);

        ImgDataConverter converter = new ImgDataConverter(fctransf);

        ForwardWT fwdDWT = ForwardWT.createInstance(converter,
                                                    pl, encSpec);

        Quantizer quant = Quantizer.createInstance(fwdDWT, encSpec);

        ROIScaler rois = ROIScaler.createInstance(quant, pl, encSpec);

        EntropyCoder ecoder =
                EntropyCoder.createInstance(rois, pl, encSpec.cblks,
                                            encSpec.pss, encSpec.bms,
                                            encSpec.mqrs, encSpec.rts,
                                            encSpec.css, encSpec.sss,
                                            encSpec.lcs, encSpec.tts);

        FileCodestreamWriter bwriter =
                new FileCodestreamWriter(dst, Integer.MAX_VALUE);

        PostCompRateAllocator ralloc =
                PostCompRateAllocator.createInstance(ecoder, pl, rate,
                                                        bwriter, encSpec);

        boolean[] imsigned = new boolean[N_COMP];
        for (int i = 0; i < N_COMP; i++) {
            imsigned[i] = src.isOrigSigned(i);
        }

        HeaderEncoder headenc =
                new HeaderEncoder(src, imsigned, fwdDWT,
                                    imgtiler, encSpec, rois, ralloc, pl);

        ralloc.setHeaderEncoder(headenc);
        headenc.encodeMainHeader();
        ralloc.initialize();
        headenc.reset();
        headenc.encodeMainHeader();
        bwriter.commitBitstreamHeader(headenc);
        ralloc.runAndWrite();
        int fileLength = bwriter.getLength();
        bwriter.close();
        
        return fileLength;
        
    }
    
    private BlkImgDataSrc DecodeFromFile(File src) throws IOException {

        ParameterList defpl, pl;
        //<editor-fold defaultstate="collapsed" desc=" Prepare parameters ">

        defpl = new ParameterList();
        String[][] param = Decoder.getAllParameters();

        for (int i = param.length - 1; i >= 0; i--) {
            if(param[i][3] != null)
                defpl.put(param[i][0], param[i][3]);
        }

        // Create parameter list using defaults
        pl = new ParameterList(defpl);

        //</editor-fold>

        BEBufferedRandomAccessFile in =
                new BEBufferedRandomAccessFile(src, "r");

        FileFormatReader ff = new FileFormatReader(in);
        ff.readFileFormat();
        if(ff.JP2FFUsed) {
            in.seek(ff.getFirstCodeStreamPos());
        }

        HeaderInfo hi = new HeaderInfo();
        HeaderDecoder hd = new HeaderDecoder(in, pl, hi);

        int nCompCod = hd.getNumComps();
        DecoderSpecs decSpec = hd.getDecoderSpecs();

        int[] depth = new int[nCompCod];
        for(int i = 0; i < nCompCod; i++) {
            depth[i] = hd.getOriginalBitDepth(i);
        }

        BitstreamReaderAgent breader = BitstreamReaderAgent
                .createInstance(in, hd, pl, decSpec,
                                pl.getBooleanParameter("cdstr_info"), hi);

        EntropyDecoder entdec = hd.createEntropyDecoder(breader, pl);

        ROIDeScaler roids = hd.createROIDeScaler(entdec, pl, decSpec);

        Dequantizer deq = hd.createDequantizer(roids, depth, decSpec);

        InverseWT invWT = InverseWT.createInstance(deq, decSpec);

        int res = breader.getImgRes();
        invWT.setImgResLevel(res);

        ImgDataConverter converter = new ImgDataConverter(invWT, 0);

        InvCompTransf ictransf = new InvCompTransf(converter, decSpec,
                                                   depth, pl);
        BlkImgDataSrc color = null;

        if(ff.JP2FFUsed && pl.getParameter("nocolorspace").equals("off")) {
            try {
                ColorSpace csMap = new ColorSpace(in, hd, pl);
                BlkImgDataSrc channels =
                        hd.createChannelDefinitionMapper(ictransf, csMap);
                BlkImgDataSrc resampled  = hd.createResampler(channels, csMap);
                BlkImgDataSrc palettized =
                        hd.createPalettizedColorSpaceMapper(resampled, csMap);
                color = hd.createColorSpaceMapper(palettized, csMap);
            } catch (ICCProfileException | ColorSpaceException ex) {
                Logger.getLogger(MainForm.class.getName())
                        .log(Level.SEVERE, null, ex);
            }

        }

        if(color == null) {
            return ictransf;
        } else {
            return color;
        }
        
    }
    
    private static int N_COMP = 3;
    
    private ImgReader hostImageRdr = null;
    private ImgReader hiddenImageRdr = null;
    
    private ImgScrollPane hostImageISP = null;
    private ImgScrollPane hiddenImageISP = null;
    
    private JFrame viewHostImageFrame = null;
    private JFrame viewHiddenImageFrame = null;
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JSpinner jBppSpinner;
    private javax.swing.JButton jChooseHiddenImageButton;
    private javax.swing.JButton jChooseHostImageButton;
    private javax.swing.JTextField jEncodedFileLengthTextField;
    private javax.swing.JPanel jHiddenImageDistPanel;
    private javax.swing.JLabel jHiddenImageLabel;
    private javax.swing.JTextField jHiddenImagePathTextField;
    private javax.swing.JPanel jHostImageDistPanel;
    private javax.swing.JLabel jHostImageLabel;
    private javax.swing.JTextField jHostImagePathTextField;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JButton jStartButton;
    private javax.swing.JButton jViewHiddenImageButton;
    private javax.swing.JButton jViewHostImageButton;
    // End of variables declaration//GEN-END:variables
}
